import { nextTick } from "vue";
import { formComponentsType, formPropsType } from './components'

//唯一ID
const uuid = () => {
  let s: any = [];
  let hexDigits = "abcdefghijklmn";
  for (let i = 0; i < 36; i++) {
    s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
  }
  s[14] = "4";
  s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
  s[8] = s[13] = s[18] = s[23] = "";
  let uuid = s.join("");
  return uuid;
}
let optionsNum = 0;
const getOptionName = (type: string, suffix: string) => {
  return type + '_' + suffix + '_' + optionsNum++;
}
const objectFormat = (obj: any, lv = 1) => {
  let firstCode = '{';
  let lastCode = '}';
  if (Array.isArray(obj)) {
    firstCode = '[';
    lastCode = ']';
  }
  let tabString = '';
  for (let i = 0; i < lv; i++) {
    tabString += '\t';
  }
  let str = firstCode + '\n';
  for (const key in obj) {
    const element = obj[key];
    if (typeof element === 'string' || typeof element === 'number') {
      str += tabString + key + ':' + '"' + element + '",\n';
    } else {
      str += tabString + (Array.isArray(obj) ? '' : (key + ':')) + objectFormat(element, lv + 1);
    }
  }
  tabString = '';
  for (let i = 0; i < lv; i++) {
    tabString += i === 0 ? '' : '\t';
  }
  str += tabString + lastCode + (lv === 1 ? ';' : ',') + '\n'
  return str;
}


export const useDesigner = () => {
  //判断是否有placeholder
  const ifHasplaceholder = (type: string) => {
    let arr = ['input', 'select', 'cascader', 'datePicker', 'textarea'];
    return arr.includes(type)
  }

  //判断是否有选项
  const ifHasOptionItem = (type: string) => {
    let arr = ['select', 'radio', 'checkbox'];
    return arr.includes(type)
  }

  //数组元素挪动
  const sortArray = (arr: Array<any>, index: number, tindex: number) => {
    if (index > tindex) {
      arr.splice(tindex, 0, arr[index]);
      arr.splice(index + 1, 1)
    }
    else {
      arr.splice(tindex + 1, 0, arr[index]);
      arr.splice(index, 1)
    }
  }

  //深拷贝
  const deepClone = (obj: Array<any>) => {
    // 判断传入obj是数组还是对象
    let objClone: never[] = [];
    if (typeof obj === 'object' && obj) {
      for (const key in obj) {
        // 判断该属性是否为这个对象本身的属性
        if (obj.hasOwnProperty(key)) {
          // 判断是否为复杂属性
          if (typeof obj[key] === 'object' && obj[key]) {
            //@ts-ignore
            objClone[key] = deepClone(obj[key]);
          } else {
            //@ts-ignore
            objClone[key] = obj[key];
          }
        }
      }
    }
    return objClone;
  }

  const addFormComponents = (newIndex: number, addItem: formComponentsType, formArray: formComponentsType[]) => {
    //删除元素
    document.querySelectorAll('.form-designer-center .leftItem').forEach(e => {
      (document.querySelector('.centerForm') as HTMLElement).removeChild(e);
    })
    //转换元素
    nextTick(() => {
      let data = JSON.parse(JSON.stringify(addItem))
      data._id = uuid()
      data.formItemProps = {
        label: data.name,
        labelPosition: 'right',
        labelWidth: 95,
        disabled: false,
        allowClear: true,
        prop: data._id,
        required: false,
        size: 'md',
        placeholder: '',
        validateType: 'string',
        pattern: '',
        enumerable: []
      }
      //级联选择器特殊处理
      if (data.type === 'cascader') {
        data.formItemProps.options = [
          {
            label: '一级',
            value: '',
            children: [
              {
                label: '二级',
                value: '',
              },
              {
                label: '二级',
                value: '',
              },
              {
                label: '二级',
                value: '',
              },
            ]
          }
        ]
      }
      //select radio checkbox 给几个默认的选项
      if (ifHasOptionItem(data.type)) {
        data.formItemProps.options = [
          { label: "选项一", value: 1 },
          { label: "选项二", value: 2 },
          { label: "选项三", value: 3 }
        ]
      }
      formArray.splice(newIndex, 0, data)
    })
  }

  //代码组装
  const generateCode = (formProps: formPropsType, formArray: formComponentsType[]) => {
    optionsNum = 0;
    let layFormItems = '';
    formArray.forEach(item => {
      let components = '';
      if (item.type === 'input') {
        components = `<lay-input
                     placeholder="${item.formItemProps.placeholder}" 
                     :disabled="${item.formItemProps.disabled}" 
                     :allow-clear="${item.formItemProps.allowClear}" 
                     size="${item.formItemProps.size}" 
                     v-model="state.${item.formItemProps.prop}"
                    />`
      } else if (item.type === 'inputNumber') {
        components = `<lay-input-number
                     placeholder="${item.formItemProps.placeholder}" 
                     :disabled="${item.formItemProps.disabled}" 
                     :allow-clear="${item.formItemProps.allowClear}" 
                     size="${item.formItemProps.size}" 
                     v-model="state.${item.formItemProps.prop}"
                    />`
      } else if (item.type === 'switch') {
        components = `<lay-switch
                     placeholder="${item.formItemProps.placeholder}" 
                     :disabled="${item.formItemProps.disabled}" 
                     :allow-clear="${item.formItemProps.allowClear}" 
                     size="${item.formItemProps.size}" 
                     v-model="state.${item.formItemProps.prop}"
                    />`
      } else if (item.type === 'textarea') {
        components = `<lay-textarea
                     placeholder="${item.formItemProps.placeholder}" 
                     :disabled="${item.formItemProps.disabled}" 
                     :allow-clear="${item.formItemProps.allowClear}" 
                     size="${item.formItemProps.size}" 
                     v-model="state.${item.formItemProps.prop}"
                    />`
      } else if (item.type === 'colorPicker') {
        components = `<lay-color-picker
                     placeholder="${item.formItemProps.placeholder}" 
                     :disabled="${item.formItemProps.disabled}" 
                     :allow-clear="${item.formItemProps.allowClear}" 
                     size="${item.formItemProps.size}" 
                     v-model="state.${item.formItemProps.prop}"
                    />`
      } else if (item.type === 'datePicker') {
        components = `<lay-date-picker
                     placeholder="${item.formItemProps.placeholder}" 
                     :disabled="${item.formItemProps.disabled}" 
                     :allow-clear="${item.formItemProps.allowClear}" 
                     size="${item.formItemProps.size}" 
                     v-model="state.${item.formItemProps.prop}"
                    />`
      } else if (item.type === 'cascader') {
        item.formItemProps.optionsName = getOptionName('cascader', 'options');
        components = `<lay-cascader
                     placeholder="${item.formItemProps.placeholder}" 
                     :disabled="${item.formItemProps.disabled}" 
                     :allow-clear="${item.formItemProps.allowClear}" 
                     size="${item.formItemProps.size}" 
                     v-model="state.${item.formItemProps.prop}"
                     :options="${item.formItemProps.optionsName}" 
                    />`
      } else if (item.type === 'rate') {
        components = `<lay-rate
                     placeholder="${item.formItemProps.placeholder}" 
                     :disabled="${item.formItemProps.disabled}" 
                     :allow-clear="${item.formItemProps.allowClear}" 
                     v-model="state.${item.formItemProps.prop}"
                    />`
      } else if (item.type === 'slider') {
        components = `<lay-slider
                     placeholder="${item.formItemProps.placeholder}" 
                     :disabled="${item.formItemProps.disabled}" 
                     :allow-clear="${item.formItemProps.allowClear}" 
                     v-model="state.${item.formItemProps.prop}"
                     :showDots="${item.formItemProps.showDots}"
                     :step="${item.formItemProps.step}"
                     :min="${item.formItemProps.min}"
                     :max="${item.formItemProps.max}"
                    />`
      } else if (item.type === 'select') {
        item.formItemProps.optionsName = getOptionName('select', 'options');
        components = `<lay-select
                     placeholder="${item.formItemProps.placeholder}" 
                     :disabled="${item.formItemProps.disabled}" 
                     :allow-clear="${item.formItemProps.allowClear}" 
                     v-model="state.${item.formItemProps.prop}"
                    >
                      <lay-select-option :value="item.value" :label="item.label" v-for="(item,i) in ${item.formItemProps.optionsName}"/>
                    </lay-select>`
      } else if (item.type === 'radio') {
        item.formItemProps.optionsName = getOptionName('radio', 'options');
        components = `<lay-radio-group
                     :disabled="${item.formItemProps.disabled}" 
                     v-model="state.${item.formItemProps.prop}"
                    >
                      <lay-radio :value="item.value" :label="item.label" v-for='(item, index) in ${item.formItemProps.optionsName}'/>
                    </lay-radio-group>`
      } else if (item.type === 'checkbox') {
        item.formItemProps.optionsName = getOptionName('checkbox', 'options');
        components = `<lay-checkbox-group
                     :disabled="${item.formItemProps.disabled}" 
                     v-model="state.${item.formItemProps.prop}"
                    >
                      <lay-checkbox skin="primary" :value="item.value" :label="item.label" v-for='(item, index) in ${item.formItemProps.optionsName}'/>
                    </lay-checkbox-group>`
      }




      let layFormItem = `
      <lay-form-item 
        label="${item.formItemProps.label}"
        prop="${item.formItemProps.required ? item.formItemProps.prop : ''}"
        label-position="${item.formItemProps.labelPosition}"
        :label-width="${item.formItemProps.labelWidth}"
      >
      `+ components + `
      </lay-form-item>
      `;
      layFormItems += layFormItem;
    })
    layFormItems += `
    <lay-form-item>
      <lay-button @click="onSubmit">提交</lay-button>
      <lay-button @click="reset">重置</lay-button>
    </lay-form-item>
    `;
    const layForm = '<lay-form required :requiredIcons="formProps.requiredIcons" ref="layFormRef" :model="state" :rules="formRules">' + layFormItems + '</lay-form>';
    const template = '<template>\n' + layForm + '\n</template>';
    //script
    const formPropsString = `\nconst formProps=${objectFormat(formProps)}`;
    let optionsString = '';
    formArray.forEach(item => {
      if (item.type === 'cascader' || item.type === 'select' || item.type === 'radio' || item.type === 'checkbox') {
        optionsString += '\n' + `const ${item.formItemProps.optionsName}=${objectFormat(item.formItemProps.options)}`;
      }
    })
    let _stateString = '';
    formArray.forEach((e, i) => {
      let val: string | number = 'null';
      if (e.type === 'checkbox') {
        val = '[]';
      } else if (e.type === 'slider') {
        val = 0;
      } else if (e.type === 'colorPicker') {
        val = '"#ffffff"';
      } else if (e.type === 'datePicker') {
        val = '""';
      }
      _stateString += '\t' + e.formItemProps.prop + ':' + val + (i === formArray.length - 1 ? '' : ',\n');
    })
    const stateString = `\nconst state = reactive({\n${_stateString}\n});\n\nconst layFormRef = ref(null);`;

    //reset
    const resetFunctionString = `\n\n//重置表单\nconst reset = ()=>{\n\tlayFormRef.value.reset();\n}`;
    //submit
    const submitFunctionString = `\n\n//提交\nconst onSubmit = ()=>{\n` +
      `\tlayFormRef.value.validate((isValidate, model, errors) => {\n

    })\n}`;

    // rules
    let rulesString = `\n\n//表单规则\nconst formRules={\n`;
    formArray.forEach(item => {
      if(item.formItemProps.required&&item.formItemProps.validateType)
      rulesString += `
      ${item.formItemProps.prop}:{${item.formItemProps.validateType!=='regexp'?`type:'${item.formItemProps.validateType}'`:'required: true'}
      ${item.formItemProps.validateType==='regexp'?`,pattern:${item.formItemProps.pattern}`:''}${item.formItemProps.validateType==='enum'?`,enum:${JSON.stringify(item.formItemProps.enumerable)}`:''}${item.formItemProps.validateMsg?`,message:'${item.formItemProps.validateMsg}'`:''}
      },`
    })
    rulesString += '}';

    const script =
      `<script setup>import { ref, reactive } from 'vue';\nimport { layer } from '@layui/layui-vue';\n`
      + formPropsString
      + optionsString
      + stateString
      + rulesString
      + resetFunctionString
      + submitFunctionString
      + '</script>';
    return template + script;
  }

  return {
    addFormComponents, ifHasOptionItem, ifHasplaceholder, sortArray, deepClone, generateCode
  };
};